/*
	YoghurtGum - 2D Game Engine

	Copyright 2009-2011 Quinten Lansu
	
	Licensed under the Apache License, Version 2.0 (the "License"); you may not 
	use this file except in compliance with the License. You may obtain a copy 
	of the License at 
		
		http://www.apache.org/licenses/LICENSE-2.0 
		
	Unless required by applicable law or agreed to in writing, software 
	distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
	WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
	License for the specific language governing permissions and limitations 
	under the License. 
*/

#ifndef _YGSTRING_H_
#define _YGSTRING_H_

#include "YGSources.h"

/*#if (YG_OS_TYPE == YG_OS_TYPE_BADA)

	#include <string.h>
	#include <stdio.h>
	#include <stdlib.h>


#endif*/

namespace YoghurtGum
{

	class String
	{

		struct ArgList;
	
	public:
	
		String();
		String(int a_Maximum);
		String(const char* a_String);
		String(const char* a_String, int a_Maximum);
#ifdef YG_STRING_WIDE_SUPPORT
		String(const wchar_t* a_String);
		String(const wchar_t* a_String, int a_Maximum);
#endif
		String(const String& a_String);
		String(const String& a_String, int a_Maximum);
		~String();

		String& Arg(char a_Number);
		String& Arg(unsigned char a_Number);
		String& Arg(short a_Number);
		String& Arg(unsigned short a_Number);
		String& Arg(long a_Number);
		String& Arg(unsigned long a_Number);
		String& Arg(int a_Number);
		String& Arg(unsigned int a_Number);
		String& Arg(float a_Number, int a_Precision = -1);
		String& Arg(double a_Number, int a_Precision = -1);
		String& Arg(const char* a_String);
#ifdef YG_STRING_WIDE_SUPPORT
		String& Arg(const wchar_t* a_String);
#endif
		String& Arg(String& a_String);

		// ================================
		// Operators
		// ================================

		bool operator ! ();

		operator char* ();
		operator wchar_t* ();

		String& operator = (const char* a_String);
		String& operator = (const String& a_String);

		String operator + (const char* a_String);
		String operator + (const String& a_String);

		String& operator += (const char* a_String);
#ifdef YG_STRING_WIDE_SUPPORT
		String& operator += (const wchar_t* a_String);
#endif
		String& operator += (const String& a_String);

		bool operator == (const char* a_String);
#ifdef YG_STRING_WIDE_SUPPORT
		bool operator == (const wchar_t* a_String);
#endif
		bool operator == (const String& a_String);

		bool operator != (const char* a_String);
		bool operator != (const String& a_String);

		// ================================
		// Iterators
		// ================================

		typedef char* iterator;
		iterator Begin();
		iterator End();
		iterator operator [] (int a_Index);

		char At(int a_Index);

		// ================================
		// Functions
		// ================================

		bool IsEmpty();

		String Middle(int a_Begin, int a_Length = -1);
		String Left(int a_Length = -1);
		String Right(int a_Length = -1);

		int FindRight(char a_Char);
		int FindLeft(char a_Char);

		bool BeginsWith(String a_String);
		bool EndsWith(String a_String);
		bool Equals(String& a_String);

		/*
			Returns a string with padding. 
			
			If a_Truncate is set to false and a_Length is smaller than the length of the string, the whole string is returned.
			If a_Truncate is set to false and a_Length is greater than the length of the string, the string with padding (a_Padding) is returned.
			If a_Truncate is set to true and a_Length is smaller than the length of the string, a_Length characters of the string is returned.
			If a_Truncate is set to true and a_Length is greater than the length of the string, the string with padding (a_Padding) is returned.
		*/
		String LeftJustified(int a_Length, char a_Padding = ' ', bool a_Truncate = false);

		bool Clear();
		bool Resize(int a_Maximum = -1);

		String& Append(const char* a_String);
#ifdef YG_STRING_WIDE_SUPPORT
		String& Append(const wchar_t* a_String);
#endif
		String& Append(const String& a_String);
		String& Prepend(const char* a_String);
#ifdef YG_STRING_WIDE_SUPPORT
		String& Prepend(const wchar_t* a_String);
#endif
		String& Prepend(const String& a_String);

		//bool SetData(char* a_String);

		char* GetData() { return m_Data; } // backwards compatibility

		const char* GetBytes() const { return m_Data; }
		int GetLength() const;
		int GetMaxLength() { return m_Maximum; }
		int GetWidth() const;

		short ToShort(bool* a_Check = 0);
		unsigned short ToUShort(bool* a_Check = 0);
		long ToLong(bool* a_Check = 0);
		unsigned long ToULong(bool* a_Check = 0);
		long long ToLongLong(bool* a_Check = 0);
		unsigned long long ToULongLong(bool* a_Check = 0);

		float ToFloat(bool* a_Check = 0);
		double ToDouble(bool* a_Check = 0);

	private:

		char* m_Data;
		int m_Length, m_Maximum, m_Size, m_Width;
		ArgList* m_ArgList;

		String& (String::*_Append)(const String&);
		String& _AppendFix(const String& a_String);
		String& _AppendDyn(const String& a_String);

		String& (String::*_Prepend)(const String&);
		String& _PrependFix(const String& a_String);
		String& _PrependDyn(const String& a_String);

		void _ArgList();
		String& _ArgHelper(const char* a_Middle, int a_Length, int a_Width = 1);
		String& _ArgHelperWide(const wchar_t* a_Middle, int a_Length);
	
	}; // class String

}; // namespace YoghurtGum

#endif
